package client

import (
	. "chess_platform/internal/common"
	"chess_platform/internal/tcp"
	"encoding/json"
	"fmt"
	"net"
	"time"
)

const EncType = 1 // 加密方式

// 发送消息给大厅服务器
func SendMsgToLobbyAndReceiveReply(uid int64, cmd uint16, msg []byte) (bool, tcp.Frame) {
	LogClient.Debug(fmt.Sprintf("发送给服务器消息:%v", string(msg)))
	ip, _ := GetLobbyServerPhpIp(uid, GetCurSvrGroup())
	return SendMsgToLobbyAndRecvReply(ip.Svrlanip, ip.Phpport, cmd, msg)
}

//TODO:需要优化
// 发送消息给全部大厅服务器
func SendMsgToCurLobby(cmd uint16, msg []byte) {
	ipinfo, _ := GetLobbyServerAllPhpIp(GetCurSvrGroup())
	for _, v := range ipinfo {
		SendMsgToLobbyAndRecvReply(v.Svrlanip, v.Phpport, cmd, msg)
	}
}
func SendMsgToAllLobby(cmd uint16, msg []byte) {
	var res []ServerLobby
	o := NewDBOrm(DBChessSysData)
	o.Raw("SELECT svrid,svrip,phpport,onlines,svrlanip FROM "+
		TableServerInfo+" WHERE svr_type=? AND `state`=1", SERVER_TYPE_LOBBY).QueryRows(&res)
	for _, v := range res {
		SendMsgToLobbyAndRecvReply(v.Svrlanip, v.Phpport, cmd, msg)
	}
}

// 发送消息到指定ip,port的服务器
func SendMsgToLobbyAndRecvReply(ip string, port int, cmd uint16, msg []byte) (bool, tcp.Frame) {
	var reply tcp.Frame
	tcpIp := fmt.Sprintf("%s:%d", ip, port)
	LogClient.Debug("--------ip:%v------ip:%v", ip, tcpIp)
	conn, err := net.Dial("tcp", tcpIp)
	if err != nil {
		LogClient.Debug("connect tcp fail:%v,%v", tcpIp, err)
		return false, reply
	}
	defer func() {
		conn.Close()
	}()
	conn.SetDeadline(time.Now().Add(5 * time.Second))
	err = tcp.WritePacket(conn, cmd, EncType, msg)
	if err != nil {
		LogClient.Debug("send tcp packet fail:%v,%v", tcpIp, err)
		return false, reply
	}
	reply, err = tcp.ReadPacket(conn)
	if err != nil {
		LogClient.Debug("read tcp packet fail:%v,%v", tcpIp, err)
		return false, reply
	}
	LogClient.Debug("connect tcp reply:%v,%v", tcpIp, string(reply.Data))
	return true, reply
}

// 修改保险箱密码
func ChangeSafePwd(uid int64, password string) bool {
	type Req struct {
		Uid int64  `json:"uid"`
		Pwd string `json:"pwd"`
	}
	req := Req{Uid: uid, Pwd: password}
	updateData := map[string]interface{}{
		"safepwd": password,
	}
	UpdateUser(updateData, uid)
	msg, _ := json.Marshal(req)
	ret, _ := SendMsgToLobbyAndReceiveReply(uid, PLAT_MSG_CHANGE_SAFEPWD, msg)
	return ret
}

// 广播消息
//1, uid != 0时,cid == 0,只发给uid
//2, uid == 0时,cid != 0,发给亲友圈名下在线进入了亲友圈的所有成员
//3, uid != 0时,cid != 0,只发给uid
//4, uid == 0时,cid == 0,全服广播
func BroadCastMsgToLobby(cid int64, msg string, uid ...int64) bool {
	type Req struct {
		Uid []int64 `json:"uid"`
		Cid int64   `json:"cid"`
		Msg string  `json:"msg"`
	}
	LogClient.Debug(fmt.Sprintf("------------send msg:%v", msg))

	req := Req{Uid: uid, Cid: cid, Msg: msg}
	LogClient.Debug(fmt.Sprintf("------------receive uid:%v", uid))
	sendMsg, _ := json.Marshal(req)
	LogClient.Debug(fmt.Sprintf("------------send marshal msg:%v", string(sendMsg)))
	SendMsgToCurLobby(PLAT_MSG_BROADCAST, sendMsg)
	return true
}

// 踢出玩家
func KillPlayerFromLobby(uid int64) bool {
	type Req struct {
		Uid int64 `json:"uid"`
	}
	req := Req{Uid: uid}
	msg, _ := json.Marshal(req)
	ret, _ := SendMsgToLobbyAndReceiveReply(uid, PLAT_MSG_KILL_PLAYER, msg)
	return ret
}

// 修改玩家数值(钻石与金币不能同时修改，否则不能保证一致性成功)
func ChangeAccountValueFromLobby(uid int64, roomCard, coin, safeCoin int64, pType, subType int) bool {
	type Req struct {
		Uid      int64 `json:"uid"`
		Rmcard   int64 `json:"rmcard"`
		Coin     int64 `json:"coin"`
		Safecoin int64 `json:"safecoin"`
		Ptype    int   `json:"ptype"`
		Sptype   int   `json:"sptype"`
	}
	req := Req{Uid: uid, Rmcard: roomCard, Coin: coin, Safecoin: safeCoin, Ptype: pType, Sptype: subType}
	msg, _ := json.Marshal(req)
	ret, frame := SendMsgToLobbyAndReceiveReply(uid, PLAT_MSG_CHANGE_ACCVALUE, msg)
	if ret == false {
		return false
	}
	type Rep struct {
		Ret  int `json:"ret"`
		Code int `json:"code"`
	}
	var rep Rep
	//ret:0-成功,1-失败
	//code: 1-成功,0-失败,2-修改金币时不在大厅不让修改
	err := json.Unmarshal(frame.Data, &rep)
	if err != nil || rep.Ret != 1 {
		return false
	}
	return true
}

// 创建私人房

// 停机维护
func NotifyStopServer() bool {
	type Req struct {
		Stop int `json:"stop"`
	}
	req := Req{Stop: 1}
	msg, _ := json.Marshal(req)
	SendMsgToAllLobby(PLAT_MSG_STOP_SERVER, msg)
	return true
}

// 关闭私人房
func ClosePlayerTable(gameType int, playType int, tableid int64) bool {
	type Req struct {
		GameType int   `json:"game_type"`
		PlayType int   `json:"play_type"`
		TableId  int64 `json:"table_id"`
	}
	req := Req{GameType: gameType, PlayType: playType, TableId: tableid}
	msg, _ := json.Marshal(req)
	ret, frame := SendMsgToLobbyAndReceiveReply(1, PLAT_MSG_CLOSE_PLAYER_TABLE, msg)
	if ret == false {
		return false
	}
	type Rep struct {
		Ret  int `json:"ret"`
		Code int `json:"code"`
	}
	var rep Rep
	err := json.Unmarshal(frame.Data, &rep)
	if err != nil || rep.Ret != 1 {
		return false
	}
	return true
}

// 通知重新加载配置文件
func NotifyReloadConfig() bool {
	type Req struct {
		Reason int `json:"reason"`
	}
	req := Req{Reason: 1}
	msg, _ := json.Marshal(req)
	SendMsgToAllLobby(PLAT_MSG_RELOAD_CONFIG, msg)

	return true
}
